package com.cavytech.wear;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.KeyguardManager;
import android.app.ProgressDialog;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothClass;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.Messenger;
import android.os.PowerManager;
import android.os.Vibrator;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.Window;
import android.widget.ListView;
import android.widget.Toast;

import java.lang.ref.WeakReference;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Set;
import java.util.concurrent.Semaphore;


public class WearActivity extends Activity {
    private static final String DEVICE_PREFIX = "Cavy";

    private static final String TAG = "WearActivity";
    public static final boolean FOR_TEST = true;
    public static final boolean FOR_HIDE_BLUETOOTH = false;

    // Added by William Chen {{{
    private BraceletClient mBraceletClient = null;
    private Messenger mBraceletMessenger = new Messenger( new MessageHandler(this, 1) );
    // }}}

    private BluetoothAdapter mBluetoothAdapter = null;

    private DeviceListAdapter mConnectedAdapter;
    private DeviceListAdapter mPairedAdapter;
    private DeviceListAdapter mDiscoveredAdapter;

    private Semaphore mDiscoverLock = new Semaphore(1);

    private MediaPlayer mAlarmSound = null;
    private Vibrator mAlarmVibrator = null;

    private ProgressDialog mProgressDialog;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
        setContentView(R.layout.activity_wear);

        setProgressBarIndeterminate(true);

        if (!FOR_HIDE_BLUETOOTH) {
            mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
            if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) {
                Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
                startActivityForResult(enableBtIntent, 1);
            }
        }

        registerReceiver(mBroadcastReceiver, new IntentFilter(BluetoothDevice.ACTION_FOUND));
        registerReceiver(mBroadcastReceiver, new IntentFilter(BluetoothDevice.ACTION_BOND_STATE_CHANGED));
        //registerReceiver(mBroadcastReceiver, new IntentFilter(BluetoothDevice.ACTION_ACL_DISCONNECTED));
        registerReceiver(mBroadcastReceiver, new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED));

        registerReceiver(mBroadcastReceiver, new IntentFilter(DeviceDataStream.STREAM_BROADCAST));


        mConnectedAdapter = new DeviceListAdapter(this, DeviceListAdapter.LISTTYPE_CONNECTED);
        mPairedAdapter = new DeviceListAdapter(this, DeviceListAdapter.LISTTYPE_PAIRED);
        mDiscoveredAdapter = new DeviceListAdapter(this, DeviceListAdapter.LISTTYPE_DISCOVERED);

        ListView connectedListView = (ListView) findViewById(R.id.ConnectedDevice);
        connectedListView.setAdapter(mConnectedAdapter);

        ListView pairedListView = (ListView) findViewById(R.id.PairedDevice);
        pairedListView.setAdapter(mPairedAdapter);

        ListView discoveredListView = (ListView) findViewById(R.id.DiscoveredDevice);
        discoveredListView.setAdapter(mDiscoveredAdapter);

        if(mBluetoothAdapter != null) {
            Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
            if (pairedDevices.size() > 0) {
                for (BluetoothDevice device : pairedDevices) {
                    if (device.getName().startsWith(DEVICE_PREFIX))
                        AddItem(BUNDLE_VALUE_PAIRED, device.getName(), device.getAddress());
                }
            }
        }

        sendBroadcast(new Intent(ServiceStarter.INVOKE_WEAR_SERVICE));

        // Added by William Chen {{{
        mBraceletClient = new BraceletClient(this, TAG, mBraceletMessenger);
        mBraceletClient.BindService();
        // After register client, we need register controller too. But the connections is not build yet, so we register controller when we receive ACK!
        // }}}

        mAlarmSound = MediaPlayer.create(this, R.raw.wear_break);
        mAlarmVibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
    }

    public static final String DISCONNECT_CALL = "DisconnectAlert";
    public static final String BATTERY_TOO_LOW_CALL = "BatteryTooLow";
    @Override
    protected void onResume() {
        super.onResume();

        if (getIntent().getBooleanExtra(DISCONNECT_CALL, false)) {

            SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
            String disconnectConfig = sharedPrefs.getString("SettingDisconnect", "0");
            if (disconnectConfig.equals("0")) {
                mAlarmSound.start();
                long[] pattern = {2000, 500, 3000, 500};
                mAlarmVibrator.vibrate(pattern, 2);
            } else if (disconnectConfig.equals("1")) {
                mAlarmSound.start();
            } else if (disconnectConfig.equals("2")) {
                long[] pattern = {2000, 500, 3000, 500};
                mAlarmVibrator.vibrate(pattern, 2);
            } else {
                return;
            }

            PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
            PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.ACQUIRE_CAUSES_WAKEUP | PowerManager.SCREEN_DIM_WAKE_LOCK, "bright");
            wl.acquire();

            KeyguardManager km = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
            final KeyguardManager.KeyguardLock kl = km.newKeyguardLock("unLock");
            kl.disableKeyguard();

            new AlertDialog.Builder(WearActivity.this)
                    .setTitle(R.string.Warning)
                    .setMessage(R.string.DeviceLost)
                    .setPositiveButton(R.string.OK, new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialoginterface, int i) {
                            mHandler.removeCallbacks(mAlertDefence);
                            mAlarmSound.stop();
                            mAlarmVibrator.cancel();
                            mBraceletClient.sendCommand(Bracelet.CMD_DEVICES, 0);
                            kl.reenableKeyguard();
                        }
                    })
                     /*
                    .setOnDismissListener(new DialogInterface.OnDismissListener() {
                        @Override
                        public void onDismiss(DialogInterface dialog) {
                            mHandler.removeCallbacks(mAlertDefence);
                            mAlarmSound.stop();
                            mAlarmVibrator.cancel();
                            mBraceletClient.sendCommand(Bracelet.CMD_DEVICES, 0);
                            kl.reenableKeyguard();
                        }
                    })
                    */
                    .setOnCancelListener(new DialogInterface.OnCancelListener() {
                        @Override
                        public void onCancel(DialogInterface dialog) {
                            mHandler.removeCallbacks(mAlertDefence);
                            mAlarmSound.stop();
                            mAlarmVibrator.cancel();
                            mBraceletClient.sendCommand(Bracelet.CMD_DEVICES, 0);
                            kl.reenableKeyguard();
                        }
                    }).show();
            getIntent().removeExtra(DISCONNECT_CALL);

            mHandler.postDelayed(mAlertDefence, 60000 * 5);

            wl.release();
        } else if (getIntent().getBooleanExtra(BATTERY_TOO_LOW_CALL, false)) {
            PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
            PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.ACQUIRE_CAUSES_WAKEUP | PowerManager.SCREEN_DIM_WAKE_LOCK, "bright");
            wl.acquire();

            KeyguardManager km = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
            final KeyguardManager.KeyguardLock kl = km.newKeyguardLock("unLock");
            kl.disableKeyguard();

            String msg = getIntent().getStringExtra("ADDRESS") + " " + getString(R.string.BatteryIsGoingToDie);

            new AlertDialog.Builder(WearActivity.this)
                    .setTitle(R.string.Warning)
                    .setMessage(msg)
                    .setPositiveButton(R.string.OK, new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialoginterface, int i) {
                            mBraceletClient.sendCommand(Bracelet.CMD_DEVICES, 0);
                            kl.reenableKeyguard();
                        }
                    })
                    .setOnCancelListener(new DialogInterface.OnCancelListener() {
                        @Override
                        public void onCancel(DialogInterface dialog) {
                            mBraceletClient.sendCommand(Bracelet.CMD_DEVICES, 0);
                            kl.reenableKeyguard();
                        }
                    }).show();
            getIntent().removeExtra(BATTERY_TOO_LOW_CALL);
            getIntent().removeExtra("ADDRESS");

            wl.release();
        } else {
            mBraceletClient.sendCommand(Bracelet.CMD_DEVICES, 0);
        }
    }

    @Override
    protected void onDestroy() {
        stopScan();

        // Added by William Chen {{{
        mBraceletClient.UnbindService();
        // }}}

        unregisterReceiver(mBroadcastReceiver);

        super.onDestroy();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_wear, menu);

        // Added by William Chen {{{
        MenuItem item = menu.findItem(R.id.TestMenuId);
        item.setVisible(FOR_TEST);
        // }}}
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

        int id = item.getItemId();

        switch (id) {
            case R.id.ScanMenuId:
                invalidateOptionsMenu();
                startScan();
                return true;

            // Added by William Chen {{{
            case R.id.TestMenuId:
                Intent intent = new Intent("cavytech.intent.action.TEST");
                startActivity(intent);

                return true;
            // }}}

            case R.id.SettingMenuId:
                startActivityForResult( new Intent( this, SettingsActivity.class ), 124 );
                return true;

            default:
                return super.onOptionsItemSelected(item);
        }
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            Intent intentHome = new Intent(Intent.ACTION_MAIN);
            intentHome.addCategory(Intent.CATEGORY_HOME);
            intentHome.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(intentHome);
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }

    @Override
    protected void onActivityResult( int requestCode, int resultCode, Intent data )
    {
        super.onActivityResult(requestCode, resultCode, data);

        if(requestCode==123) {
            int rtn = data.getIntExtra("RTN_CODE", 2);

            switch(rtn) {
                case 0:
                    break;
                case 1:
                    mBraceletClient.sendCommand(1002, 1, mStateAddress);
                    break;
                case 2:
                    break;
            }
        } else if(requestCode==124) {
            switch ( resultCode ) {
                case 1:
                    mBraceletClient.sendCommand( 1003, data.getIntExtra("LINK_LOST", 2) );
                    break;
                case 2:
                    mBraceletClient.sendCommand( 1004, data.getIntExtra("HID_ENABLE", 2) );
                    break;
                case 3:
                    try {
                        // GioChen Todo : send command in state machine or thread to avoid frame lost.
                        mBraceletClient.sendCommand(1003, data.getIntExtra("LINK_LOST", 2));
                        Thread.sleep(1000);
                        mBraceletClient.sendCommand(1004, data.getIntExtra("HID_ENABLE", 2));
                    } catch ( Exception e ) {
                        e.printStackTrace();
                    }
                    break;
            }
        }
    }

    private Runnable mAlertDefence = new Runnable() {
        @Override
        public void run() {
            mAlarmSound.stop();
            mAlarmVibrator.cancel();
            mBraceletClient.sendCommand(Bracelet.CMD_DEVICES, 0);
        }
    };

    private Runnable mDialogDefence = new Runnable() {
        @Override
        public void run() {
            if (mProgressDialog != null && mProgressDialog.isShowing())
                mProgressDialog.dismiss();
        }
    };

    private void DialogShow(String title, String content, int duty) {
        if (duty >= 0)
            mHandler.postDelayed(mDialogDefence, duty);

        mProgressDialog = ProgressDialog.show(WearActivity.this, title, content, true);
    }

    private void DialogDismiss() {
        mHandler.removeCallbacks(mDialogDefence);
        if (mProgressDialog != null && mProgressDialog.isShowing())
            mProgressDialog.dismiss();
    }

    private void DialogUpdate( String title, String content, boolean updateDuty, int duty ) {
        if ( mProgressDialog != null && mProgressDialog.isShowing() ) {
            if ( updateDuty )
                mHandler.removeCallbacks(mDialogDefence);
            mProgressDialog.setMessage( content );
            if ( updateDuty && duty >= 0 )
                mHandler.postDelayed(mDialogDefence, duty);
        } else {
            DialogShow( title, content, duty );
        }

    }

    private Runnable mStopRunnable = new Runnable() {
        @Override
        public void run() {
            stopScan();
        }
    };

    private void startScan() {
        if(mBluetoothAdapter==null)
            return;

        try {
            mDiscoverLock.acquire();
            mDiscoveredAdapter.removeAllItem();
            setProgressBarIndeterminateVisibility(true);

            if (mBluetoothAdapter.isDiscovering()) {
                mBluetoothAdapter.cancelDiscovery();
                mHandler.removeCallbacks(mStopRunnable);
            }

            mBluetoothAdapter.startDiscovery();
            mHandler.postDelayed(mStopRunnable, 5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            mDiscoverLock.release();
        }
    }

    private void stopScan() {
        if(mBluetoothAdapter==null)
            return;
        try {
            mDiscoverLock.acquire();
            if (mBluetoothAdapter.isDiscovering()) {
                mBluetoothAdapter.cancelDiscovery();
                setProgressBarIndeterminateVisibility(false);
            }

        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            mDiscoverLock.release();
        }
    }

    private Handler mHandler = new MessageHandler(this, 0);

    private static class MessageHandler extends Handler {
        private final WeakReference<WearActivity> mActivity;
        private int mMethod = 0;

        public MessageHandler(WearActivity activity, int methodNum) {
            mActivity = new WeakReference<WearActivity>(activity);
            mMethod = methodNum;
        }

        @Override
        public void handleMessage(Message msg) {
            WearActivity activity = mActivity.get();
            if (activity == null)
                return;
            switch (mMethod) {
                case 0:
                    activity.handleMessage(msg);
                    break;
                case 1:
                    activity.serviceMessage(msg);
                    break;
            }
        }
    }

    private void handleMessage(Message msg) {

        int list = msg.getData().getInt(BUNDLE_KEY_LIST);
        String address = msg.getData().getString(BUNDLE_KEY_ADDRESS);
        String name = msg.getData().getString(BUNDLE_KEY_NAME);

        switch (msg.what) {
            case MSG_REMOVE_FROM_LIST:
                RemoveItem(list, address);
                break;
            case MSG_ADD_TO_LIST:
                AddItem(list, name, address);
                break;
            case MSG_REBUILD_PAIRED: {
                if ( mBluetoothAdapter == null ) break;
                Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
                mPairedAdapter.removeAllItem();
                if (pairedDevices.size() > 0) {
                    for (BluetoothDevice device : pairedDevices) {
                        AddItem(BUNDLE_VALUE_PAIRED, device.getName(), device.getAddress());
                    }
                }
            }
            break;

            case MSG_CONNECT_FAILED:
                Toast.makeText(getApplicationContext(), R.string.ConnectionFailed, Toast.LENGTH_SHORT).show();
                break;
        }
    }

    private boolean mDisconnecting = false;
    private int mPrevConnectDeviceNumber = 0;
    private void serviceMessage( Message msg ) {
        Bracelet.dump(TAG + "(RECV)", msg);
        switch (msg.what) {
            case Bracelet.CMD_ACK:

                // When we receive ACK for CMD_REG_CLIENT, send CMD_REG_CONTROLLER.
                if(msg.arg1 == Bracelet.CMD_REG_CLIENT) {
                    mBraceletClient.sendCommand(Bracelet.CMD_REG_CONTROLLER, Bracelet.ARG_REGISTER);

                } else if (msg.arg1 == Bracelet.CMD_REG_CONTROLLER) {
                    mBraceletClient.sendCommand(Bracelet.CMD_DEVICES, 0);

                } else if (msg.arg1 == Bracelet.CMD_DEVICES) {
                    ArrayList<String> deviceList = msg.getData().getStringArrayList(Bracelet.KEY_STRING_ARRAY);

                    mConnectedAdapter.removeAllItem();
                    if(deviceList != null) {
                        for (String s : deviceList) {
                            AddItem(BUNDLE_VALUE_CONNECTED, BluetoothAdapter.getDefaultAdapter().getRemoteDevice(s).getName(), s);
                        }
                    }

                    mPairedAdapter.removeAllItem();
                    if(mBluetoothAdapter != null) {
                        Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
                        if (pairedDevices.size() > 0) {
                            for (BluetoothDevice device : pairedDevices) {
                                if (device.getName().startsWith(DEVICE_PREFIX) && !mConnectedAdapter.isItemExist(device.getAddress()))
                                    AddItem(BUNDLE_VALUE_PAIRED, device.getName(), device.getAddress());
                            }
                        }
                    }

                    // GioChen Todo: This is test function...
                    /*
                    if ( mPrevConnectDeviceNumber == 0 && deviceList.size() == 1 ) {
                        Intent intentBluetooth = new Intent();
                        intentBluetooth.setAction(android.provider.Settings.ACTION_BLUETOOTH_SETTINGS);
                        startActivity(intentBluetooth);
                    }
                    */
                    mPrevConnectDeviceNumber = deviceList.size();

                } else if (msg.arg1 == Bracelet.CMD_CONNECTION) {
                    if ( mDisconnecting ) {
                        mBraceletClient.sendCommand(Bracelet.CMD_DEVICES, 0);
                        DialogDismiss();
                        mDisconnecting = false;
                    }

                } else if (msg.arg1 == 1001) {
                    Intent intent = new Intent(getBaseContext(), StateActivity.class);
                    intent.putExtra("SYSTEM",msg.getData().getByteArray(Bracelet.KEY_BYTE_ARRAY));
                    startActivityForResult(intent, 123);
                } else if (msg.arg1 == 1002) {
                }
                break;
            case Bracelet.CMD_DATA:
                mBraceletClient.sendACK(msg, true);
                // Todo: We get data from Client here.Send data to BT device now!
                break;
            case Bracelet.CMD_CONNECTION:
                String address = new String( msg.getData().getString(Bracelet.KEY_STRING ) );
                Log.d( TAG, "Connect " + address + " " + (msg.arg1 == 0 ? "OK" : "NG") );
                // Todo : toast OK or NG...
                DialogDismiss();
                if ( msg.arg1 != 0 ) {
                    Toast.makeText( this,
                            getString( R.string.ConnectTo ) +
                            new String( msg.getData().getString(Bracelet.KEY_STRING) ) +
                            getString( R.string.Failed ), Toast.LENGTH_LONG ).show();
                }

                mBraceletClient.sendACK(msg, true);

                mBraceletClient.sendCommand(Bracelet.CMD_DEVICES, 0);
                break;
            default:
                break;
        }
    }

    private void RemoveItem( int list, String address ) {
        switch ( list ) {
            case BUNDLE_VALUE_PAIRED:
                mPairedAdapter.removeItem(address);
                break;
            case BUNDLE_VALUE_CONNECTED:
                mConnectedAdapter.removeItem(address);
                break;
            case BUNDLE_VALUE_DISCOVERED:
                mDiscoveredAdapter.removeItem(address);
                break;
        }

    }

    private void AddItem( int list, String name, String address ) {
        switch (list) {
            case BUNDLE_VALUE_PAIRED:
                mPairedAdapter.addItem(name, address,
                        new DeviceOnClickListener(address, DeviceListAdapter.LISTTYPE_PAIRED, ACTION_CONNECT),
                        new DeviceOnClickListener(address, DeviceListAdapter.LISTTYPE_PAIRED, ACTION_UNPAIR));

                break;
            case BUNDLE_VALUE_CONNECTED:
                mConnectedAdapter.addItem(name, address,
                        new DeviceOnClickListener(address, DeviceListAdapter.LISTTYPE_CONNECTED, ACTION_STATE),
                        new DeviceOnClickListener(address, DeviceListAdapter.LISTTYPE_CONNECTED, ACTION_DISCONNECT));
                break;
            case BUNDLE_VALUE_DISCOVERED:
                mDiscoveredAdapter.addItem(name, address,
                        new DeviceOnClickListener(address, DeviceListAdapter.LISTTYPE_DISCOVERED, ACTION_PAIR), null);
                break;
        }
    }

    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive( Context context, Intent intent ) {
            if ( BluetoothDevice.ACTION_FOUND.equals( intent.getAction() ) ) {
                BluetoothDevice device = intent.getParcelableExtra( BluetoothDevice.EXTRA_DEVICE );
                if ( device.getName() != null && device.getName().startsWith( DEVICE_PREFIX ) && !mPairedAdapter.isItemExist(device.getAddress()) ) {
                    AddItem(BUNDLE_VALUE_DISCOVERED, device.getName(), device.getAddress());
                }

            } else if ( BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals( intent.getAction() ) ) {
                BluetoothDevice device = intent.getParcelableExtra( BluetoothDevice.EXTRA_DEVICE );

                switch ( device.getBondState() ) {
                    case BluetoothDevice.BOND_NONE:
                        //Log.d( TAG, "BOND_NONE " + device.getName() + " " + device.getAddress() );
                        DialogDismiss();
                        break;
                    case BluetoothDevice.BOND_BONDING:
                        //Log.d( TAG, "BOND_BONDING " + device.getName() + " " + device.getAddress() );
                        DialogShow(getString(R.string.Pairing), getString(R.string.WaitAMoment) + "...", 15000);
                        break;
                    case BluetoothDevice.BOND_BONDED:
                        AddItem( BUNDLE_VALUE_PAIRED, device.getName(), device.getAddress() );
                        RemoveItem( BUNDLE_VALUE_DISCOVERED, device.getAddress() );
                        DialogDismiss();
                        break;
                }

            } else if ( BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals( intent.getAction() ) ) {
                Log.i( TAG, "Discovery done." );

            } else if ( DeviceDataStream.STREAM_BROADCAST.equals( intent.getAction() ) ) {

                switch ( intent.getIntExtra(DeviceDataStream.STREAM_PARAM, DeviceDataStream.PARAM_END_CAL)) {
                    case DeviceDataStream.PARAM_START_CAL:
                        DialogUpdate( getString(R.string.Calibration), getString(R.string.CalibrationAction), true, 60000 );
                        break;
                    case DeviceDataStream.PARAM_PROC_CAL:
                        DialogUpdate( getString(R.string.Calibration), getString(R.string.CalibrationStore), true, 10000 );
                        break;
                    case DeviceDataStream.PARAM_END_CAL:
                        DialogDismiss();
                        break;
                }

            } else {
                Log.i( TAG, "Unknow : " + intent.getAction() );
            }
        }
    };


    private String mStateAddress;
    private static final int MSG_REMOVE_FROM_LIST = 1001;
    private static final int MSG_ADD_TO_LIST = 1002;
    private static final int MSG_REBUILD_PAIRED = 1003;
    private static final int MSG_CONNECT_FAILED = 1004;

    private static final String BUNDLE_KEY_LIST = "LIST";
    private static final String BUNDLE_KEY_ADDRESS = "ADDRESS";
    private static final String BUNDLE_KEY_NAME = "NAME";

    private static final int BUNDLE_VALUE_PAIRED = 1010;
    private static final int BUNDLE_VALUE_CONNECTED = 1011;
    private static final int BUNDLE_VALUE_DISCOVERED = 1012;

    private static final int ACTION_CONNECT = 101;
    private static final int ACTION_UNPAIR = 102;
    private static final int ACTION_PAIR = 103;
    private static final int ACTION_DISCONNECT = 104;
    private static final int ACTION_STATE = 105;
    private class DeviceOnClickListener implements View.OnClickListener {
        private String mAddress;
        private int mList;
        private int mAction;

        public DeviceOnClickListener( String address, int list, int action ) {
            mAddress = address;
            mAction = action;
            mList = list;
        }

        public void SendToUI( int what, int list, String name ) {
            Message msg;
            Bundle bundle;

            msg = new Message();
            bundle = new Bundle();
            msg.what = what;
            bundle.putInt( BUNDLE_KEY_LIST, list );
            bundle.putString( BUNDLE_KEY_ADDRESS , mAddress );
            bundle.putString( BUNDLE_KEY_NAME, name );
            msg.setData( bundle );

            mHandler.sendMessage( msg );
        }

        @Override
        public void onClick( View v ) {

            stopScan();

            switch ( mList ) {
                case DeviceListAdapter.LISTTYPE_CONNECTED:
                    switch ( mAction ) {
                        case ACTION_STATE:
                            mStateAddress = mAddress;
                            mBraceletClient.sendCommand(1001, 1, mAddress);
                            break;
                        case ACTION_DISCONNECT:
                            DialogShow( getString(R.string.Disconnecting), getString(R.string.WaitAMoment) + "...", 10000 );
                            mBraceletClient.sendCommand(Bracelet.CMD_CONNECTION, 1, mAddress);
                            mDisconnecting = true;
                            break;
                    }
                    break;

                case DeviceListAdapter.LISTTYPE_PAIRED:
                    switch ( mAction ) {
                        case ACTION_CONNECT:
                            DialogShow( getString(R.string.Connecting), getString(R.string.WaitAMoment) + "...", 60000 );
                            mBraceletClient.sendCommand(Bracelet.CMD_CONNECTION, 0, mAddress);
                            break;
                        case ACTION_UNPAIR:
                            if ( mBluetoothAdapter == null ) break;
                            BluetoothDevice device = mBluetoothAdapter.getRemoteDevice( mAddress );
                            try {
                                Method m = device.getClass().getMethod( "removeBond", ( Class[] ) null );
                                m.invoke(device, ( Object[] ) null );
                            } catch ( Exception e ) {
                                Log.e( TAG, e.getMessage() );
                            }
                            SendToUI( MSG_REMOVE_FROM_LIST, BUNDLE_VALUE_PAIRED, mBluetoothAdapter.getRemoteDevice( mAddress ).getName() );
                            break;
                    }
                    break;

                case DeviceListAdapter.LISTTYPE_DISCOVERED:
                    if ( mBluetoothAdapter == null ) break;
                    BluetoothDevice device = mBluetoothAdapter.getRemoteDevice( mAddress );
                    try {
                        Method m = device.getClass().getMethod( "createBond", ( Class[] ) null );
                        m.invoke( device, ( Object[] ) null );
                    } catch ( Exception e ) {
                        Log.e( TAG, e.getMessage() );
                    }
                    break;
            }

        }
    }

}
